#include "HAL_Uart_Driver.h"


/* UART Events Example
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/timers.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "y_ringbuf.h"
#include "shell.h"
#include "freertos/semphr.h"
static const char *TAG = "uart_events";
// 声明一个TimerHandle_t类型的变量，用于存储定时器句柄
static RINGBUF_st *receive_ringbuf;
// 声明一个TimerHandle_t类型的变量，用于存储定时器句柄
static TimerHandle_t uart_Timerout;

static QueueHandle_t data_deal_handle_Queue;  //数据处理队列

SemaphoreHandle_t debug_Mutex;
uart_status_t uart_status =  uart_idle;


uint8_t Uart_Receive_WriteBuffer[512] = {0};

SemaphoreHandle_t xMutex;

#define EX_UART_NUM UART_NUM_0
#define PATTERN_CHR_NUM    (3)         /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/

#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;





/*********************************************************************************
* function   :   uart_event_task     
* Description :  串口事件处理任务
* Input       :  
* Output      :  
* Author      :                    Data : 2024 05.10
**********************************************************************************/	
static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    size_t buffered_size;
    //uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
    
    uint8_t* data = (uint8_t *) heap_caps_malloc(RD_BUF_SIZE,MALLOC_CAP_8BIT);
	int receive_len = 0;
    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(uart0_queue, (void * )&event, portMAX_DELAY)) {
            // bzero(dtmp, RD_BUF_SIZE);
            // bzero(data, RD_BUF_SIZE);
            
            CONSOLE_DEBUG(TAG, "uart[%d] event:", EX_UART_NUM);
            switch(event.type) {
                //Event of UART receving data
                /*We'd better handler data event fast, there would be much more data events than
                other types of events. If we take too much time on data event, the queue might
                be full.*/
                case UART_DATA:
                    CONSOLE_DEBUG(TAG, "[UART DATA]: %d", event.size);
                    #if 0
                    uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
                    CONSOLE_DEBUG(TAG, "[DATA EVT]:");
                    uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size);
                    #else
                    if(event.size > 0)
						{
							// 启动定时器，第二个参数为定时器超时时间，设置为0表示立即启动
							if(uart_status == uart_idle)
							{
								uart_status = uart_receving;
								xTimerStart(uart_Timerout, 0);
							}else if(uart_status == uart_receving)
							{
								if(xTimerIsTimerActive(uart_Timerout) != pdFALSE)
								{
                           
								    xTimerReset(uart_Timerout,0);
								}else{
								
								}
									if(event.size <= uart_fifo_size)
									{
											uart_status = uart_receving;
									}	
							}


							receive_len =  event.size;
					
							//printf("UART_DATA receive data size =%d\r\n",event.size);
							int len = uart_read_bytes(EX_UART_NUM, (uint8_t* )data, event.size,/*uart_timerout_times / portTICK_PERIOD_MS*/portMAX_DELAY);
                             
							receive_len =  len;

			
							y_ringbuf_write(receive_ringbuf, (uint8_t* )data, receive_len);
						

				
					}


                    #endif
                    break;
                //Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    CONSOLE_DEBUG(TAG, "hw fifo overflow");
                    // If fifo overflow happened, you should consider adding flow control for your application.
                    // The ISR has already reset the rx FIFO,
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;
                //Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    CONSOLE_DEBUG(TAG, "ring buffer full");
                    // If buffer full happened, you should consider encreasing your buffer size
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;
                //Event of UART RX break detected
                case UART_BREAK:
                    CONSOLE_DEBUG(TAG, "uart rx break");
                    break;
                //Event of UART parity check error
                case UART_PARITY_ERR:
                    CONSOLE_DEBUG(TAG, "uart parity error");
                    break;
                //Event of UART frame error
                case UART_FRAME_ERR:
                    CONSOLE_DEBUG(TAG, "uart frame error");
                    break;
                //UART_PATTERN_DET
                case UART_PATTERN_DET:
                    // uart_get_buffered_data_len(EX_UART_NUM, &buffered_size);
                    // int pos = uart_pattern_pop_pos(EX_UART_NUM);
                    // CONSOLE_DEBUG(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size);
                    // if (pos == -1) {
                    //     // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
                    //     // record the position. We should set a larger queue size.
                    //     // As an example, we directly flush the rx buffer here.
                    //     uart_flush_input(EX_UART_NUM);
                    // } else {
                    //     uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS);
                    //     uint8_t pat[PATTERN_CHR_NUM + 1];
                    //     memset(pat, 0, sizeof(pat));
                    //     uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
                    //     CONSOLE_DEBUG(TAG, "read data: %s", dtmp);
                    //     CONSOLE_DEBUG(TAG, "read pat : %s", pat);
                    // }
                    break;
                //Others
                default:
                    CONSOLE_DEBUG(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }
    // free(dtmp);
    free(data);
    // dtmp = NULL;
    data = NULL;
    vTaskDelete(NULL);
}



/*********************************************************************************
* function   :   uart_timerout_Callback     
* Description :  串口超时回调函数
* Input       :  
* Output      :  
* Author      :                    Data : 2024 05.10
**********************************************************************************/	
void uart_timerout_Callback(TimerHandle_t xTimer) {
    // 在这里执行定时器超时后的任务
    // 注意：回调函数中不要执行耗时的操作，避免影响其他任务的运行

	int length = 0 ;

	if(uart_status == uart_idle)
	{
		return ;
	}
	else if(uart_status == uart_receving)
	{

		xQueueSend(data_deal_handle_Queue, &length, portMAX_DELAY);  //直接发送到处理函数
	
		uart_status = uart_idle;
	}else if(uart_status == uart_receive_complete)
	{
		//printf("uart_receive_complete-----%s----\r\n",__FUNCTION__);
		uart_status = uart_idle;
	}

}





/*********************************************************************************
* function   :   deal_data_callback_handler     
* Description :  数据处理任务
* Input       :  
* Output      :  
* Author      :                    Data : 2024 05.10
**********************************************************************************/	
void deal_data_callback_handler()
{
  int length = 0;

  while (1) {
                // 从队列中接收数据
                if(xQueueReceive(data_deal_handle_Queue, &length, portMAX_DELAY) == pdPASS) {

                        bzero(Uart_Receive_WriteBuffer, sizeof(Uart_Receive_WriteBuffer));
                        
                        int user_size = y_ringbuf_get_used_size(receive_ringbuf);
                        y_ringbuf_read_clear(receive_ringbuf, (uint8_t *)Uart_Receive_WriteBuffer, user_size);

                        shell_callback_handler((char *)Uart_Receive_WriteBuffer,user_size);

                        // printf("user_size = %d\r\n",user_size);
                        // ESP_LOGI(TAG,"read len %d\r\n",user_size); 
                        // ESP_LOGI(TAG,"%s\r\n",Uart_Receive_WriteBuffer); 
                        // if(user_size!=0)
                        // {
                        //     for(int i = 0;i<user_size;i++)
                        //     printf("%c",data[i]);
                        //     printf("\r\n");
                        // }
                }
    }
    vTaskDelete(NULL);
}




/*********************************************************************************
* function   :   Console_Timer_Reset     
* Description :  串口超时定时器重置
* Input       :  
* Output      :  
* Author      :                    Data : 2024 05.10
**********************************************************************************/	
void Console_Timer_Reset()
{
	xTimerReset(uart_Timerout,0);	
    uart_flush(EX_UART_NUM);	
    uart_wait_tx_idle_polling(EX_UART_NUM);			
}




/*********************************************************************************
* function   :   Console_Uart_Init     
* Description :  命令行串口驱动初始化
* Input       :  
* Output      :  
* Author      :                    Data : 2024 05.10
**********************************************************************************/	
void Console_Uart_Init(void)
{
    
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
    uart_param_config(EX_UART_NUM, &uart_config);

    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    uart_flush(EX_UART_NUM);

    //Set uart pattern detect function.
    // uart_enable_pattern_det_baud_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
    // //Reset the pattern queue length to record at most 20 pattern positions.
    // uart_pattern_queue_reset(EX_UART_NUM, 20);

	//创建串口超时定时器
	uart_Timerout = xTimerCreate(
	    "uart_Timer",              // 定时器名称（可以为NULL）
	    pdMS_TO_TICKS(uart_timerout_times),     // 定时器超时时间（以毫秒为单位）
	    pdFALSE,                 // 定时器为周期性（pdTRUE）还是单次（pdFALSE）
	    5,                      // 定时器ID（可以为0）
	    uart_timerout_Callback          // 定时器回调函数
	);;

    //创建循环队列接受数据
    receive_ringbuf = y_ringbuf_create(buffer_size);
    if (receive_ringbuf == NULL) {
       printf("receive_ringbuf init fail");
    }

    data_deal_handle_Queue = xQueueCreate(10, sizeof(int));  //数据处理队列


     // 创建互斥量
    xMutex = xSemaphoreCreateMutex();
	//数据处理函数	
	xTaskCreate(deal_data_callback_handler, "deal_data_task", 1024*2, NULL, 10/*configMAX_PRIORITIES*/, NULL);
    //Create a task to handler UART event from ISR
    xTaskCreate(uart_event_task, "uart_event_task", 1024*2, NULL,10/*configMAX_PRIORITIES -1*/, NULL);
}